<?php

namespace App\Services;

use App\Common\Libs\ArrayHelper;
use App\Common\Libs\Dispatch\Queue;
use App\Common\Libs\IdBuilder;
use App\Consts\GlobalCommentConst;
use App\Consts\GlobalConst;
use App\Consts\GlobalCounterConst;
use App\Consts\GlobalNoteConst;
use App\Consts\GlobalQueueConst;
use App\Events\CreateCommentEvent;
use App\Events\DelCommentEvent;
use App\Exceptions\Error;
use App\Jobs\Controller\CommentJob;
use App\Models\Cache\CacheKey;
use App\Models\Field\CommentField;
use App\Models\Field\UserField;
use Illuminate\Support\Facades\DB;

class CommentService extends BaseService
{
    private $_repository;

    public function __construct()
    {
        parent::__construct();
        $this->_repository = repository()->CommentRepository;
    }

    /**
     * 获取评论列表
     * @param $searchParams
     * @return array|mixed
     */
    public function getCommentList($searchParams)
    {
        $dataProvider = $this->_repository->getCommentList($searchParams);
        $pagination = $this->getPagination();
        $comments = $dataProvider->get();

        if (empty($comments)) {
            return $this->searchList['count'];
        }

        $comments = collect($comments->toArray());

        // 用户
        $userIdArr = $comments->pluck('user_id')->all();
        $users = repository()->UserRepository->getUserByUserIdArr($userIdArr);
        $users = ArrayHelper::index($users, 'user_id');

        // 点赞
        $likes = service()->LikeService->getLikeListByTargetType($searchParams['current_user_id'], GlobalConst::TARGET_TYPE_COMMENT);
        $likes = ArrayHelper::index($likes, 'target_id');

        $list = [];
        foreach ($comments as $comment) {
            $comment = CommentField::format($comment, CommentField::getFormats(CommentField::SELF_LIST));
            $count = service()->CounterService->getTargetCount(
                CacheKey::COUNTER_COMMENT, ['reply', 'like'], ['comment_id' => $comment['id']]
            );
            $comment['type'] = GlobalCommentConst::COMMENT_TYPE_COMMENT;
            $comment['is_like'] = (int)(isset($likes[$comment['id']]) && $likes[$comment['id']]['is_deleted'] == GlobalConst::IS_NOT_DELETE);
            $comment['user'] = UserField::format($users[$comment['user_id']], UserField::getFormats(UserField::BASE_INFO));
            $comment['count'] = $count;
            $comment['like'] = $count['like'];
            $comment['reply'] = service()->ReplyService->getReplyListByCommentId([
                'comment_id' => $comment['id'],
                'current_user_id' => $searchParams['current_user_id']
            ]);
            $list[] = $comment;
        }

        if ($searchParams['order'] == GlobalCommentConst::ORDER_HOT) {
            $list = ArrayHelper::multiSort($list, 'like', SORT_DESC);
        }

        return self::outputTotalCountList($dataProvider, $pagination, $list);
    }

    /**
     * 新增评论
     * @param $loadData
     * @return array|bool
     */
    public function addComment($loadData)
    {
        // 私密笔记不可评论
        if ($loadData['target_type'] == GlobalConst::TARGET_TYPE_NOTE) {
            $note = repository()->NoteRepository->getNoteById($loadData['target_id']);
            if ((!$note || ($note && $note->is_deleted == GlobalConst::IS_DELETED) || ($note && $note->is_public == GlobalNoteConst::IS_NOT_PUBLIC)) && $loadData['user_id'] != $note->user_id) {
                return false;
            }
        }

        $loadData = ArrayHelper::merge($loadData, [
            'comment_id' => IdBuilder::getUniqueID(),
            'is_deleted' => GlobalConst::IS_NOT_DELETE
        ]);

        DB::beginTransaction();
        try {
            $noteType = GlobalConst::DEFAULT_TARGET_DETAIL_TYPE;

            if ($loadData['target_type'] == GlobalConst::TARGET_TYPE_NOTE) {
                $note = service()->NoteService->getNote($loadData['target_id']);
                if ($note) {
                    $noteType = $note->type;
                }
            }
            $loadData['note_type'] = $noteType;

            // 新增评论
            $comment = repository()->CommentRepository->addComment($loadData);
            $data = [
                'comment_id' => $loadData['comment_id'],
                'user_id' => $loadData['user_id'],
                'target_id' => $loadData['target_id'],
                'target_type' => $loadData['target_type']
            ];
            // 【暂时】新增索引表记录
            repository()->CommentRepository->addIndexComment(ArrayHelper::merge($data, [
                'type' => GlobalConst::TARGET_TYPE_COMMENT,
            ]));

            // 同步更新主体计数
            $this->_editCount($loadData['target_id'], $loadData['target_type']);

            /**
             * 队列做以下几件事：
             *  1. 修改【评论】是否为主体发布者发布
             *  2. 发送消息
             *  3. 记录日志
             */
            CreateCommentEvent::dispatch($comment);

            DB::commit();

            return ArrayHelper::merge($comment->commonFormat(), [
                'id' => $loadData['comment_id']
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return Error::throw($e);
        }
    }

    /**
     * 删除评论
     * @param $commentId
     * @param $currentUserId
     * @return \Illuminate\Http\JsonResponse|array
     */
    public function delComment($commentId, $currentUserId)
    {
        DB::beginTransaction();
        try {
            // 获取评论
            $comment = repository()->CommentRepository->getComment($commentId);
            if (!$comment || $comment->user_id !== $currentUserId) {
                return Error::handle(lang('Unauthorized'));
            }

            // 删除评论
            repository()->CommentRepository->delComment($comment);

            // 【暂时】删除索引表记录
            repository()->CommentRepository->delIndexComment($comment);

            // 更新【评论】的【可见性】和【删除态】，这里需要同步，因为有回复的已删除的评论一九显示
            service()->CommentService->changeStatusByQueue([
                'comment_id' => $comment['comment_id'],
                'target_id' => $comment['target_id'],
                'target_type' => $comment['target_type'],
            ], 'sync');

            DelCommentEvent::dispatch($comment);

            DB::commit();

            return $comment->commonFormat();
        } catch (\Exception $e) {
            DB::rollBack();
            return Error::throw($e);
        }
    }

    /**
     * 获取评论的主体的用户
     * @param $comment
     * @return bool|string
     */
    public function getTargetUserId($comment)
    {
        $receiveUserId = '';
        if ($comment['target_type'] == GlobalConst::TARGET_TYPE_NOTE) {
            $note = repository()->NoteRepository->getNoteByNoteId($comment['target_id']);
            if ($note) {
                $receiveUserId = $note['user_id'];
            }
        }
        if ($comment['target_type'] == GlobalConst::TARGET_TYPE_DYNAMIC) {
            $dynamic = repository()->DynamicRepository->getDynamicById($comment['target_id']);
            if ($dynamic) {
                $receiveUserId = $dynamic['user_id'];
            }
        }

        return $receiveUserId ?? false;
    }

    /**
     * 评论删除后，该评论如果没有正常的回复
     *  1. is_deleted = 1【已删除】
     *  2. is_view = 0【不可见】
     *  3. 评论的主体的评论数 - 1
     * @param array $commentInfo ['comment_id' ='', 'target_id' =>'', 'target_type' => '']
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public function changeStatusByQueue($commentInfo, $driver = 'queue')
    {
        return Queue::getInstance(CommentJob::class)
            ->push($commentInfo, GlobalQueueConst::COMMENT_CHANGE_STATUS, $driver);
    }

    /**
     * 评论/回复后修改是否有主体发布者的评论/回复
     * @param array $commentInfo ['comment_id' ='', 'user_id' => '', 'target_id' =>'', 'target_type' => '']
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public function changeHaveAuthorReplyByQueue($commentInfo)
    {
        return Queue::getInstance(CommentJob::class)
            ->push($commentInfo, GlobalQueueConst::COMMENT_CHANGE_AUTHOR_REPLY);
    }

    /**
     * 点赞/取消点赞后修改<hot> +1/-1
     * @param $data ['comment_id' => '', 'trend' => '']
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public function changeHotByQueue($data)
    {
        return Queue::getInstance(CommentJob::class)
            ->push($data, GlobalQueueConst::COMMENT_CHANGE_HOT);
    }

    /**
     * 同步评论主体的缓存计数
     * @param string $targetId
     * @param int $targetType
     * @param int $trend
     * @return bool
     */
    public function _editCount($targetId, $targetType, $trend = GlobalCounterConst::INCREASE)
    {
        service()->CounterService->editTargetCountByTargetType($targetId, $targetType, GlobalCounterConst::COUNT_COMMENT, $trend);

        return true;
    }
}
